//
//  YLWebVC.swift
//  iosh5vue
//
//  Created by lyl on 2021/3/1.
//  Copyright © 2021 lyl. All rights reserved.
//

import UIKit
import WebKit
import JavaScriptCore

/*
 使用方法1：继承
 class YLHomepageVC: YLWebVC {
     override func initData() {
         loadPage("index")
     }
 }
 使用方法2：跳转
 let vc = YLWebVC()
 vc.url = "https://www.baidu.com"
 navigationController?.pushViewController(vc, animated: true)
 */

struct Listener {
    var isAdd: Bool
    var name: String
    var callback: ((Any)->Void)
}

class YLWebVC: UIViewController, WKScriptMessageHandler, WKNavigationDelegate {
    var url: String!
    var wkwebview: WKWebView!
    var wkconfiguration: WKWebViewConfiguration!
    private var listeners = [Listener]()//自定义的监听
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        initUI()
        initData()
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        addListener()
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        clearListener()
    }
    
    deinit {
        MyLog("------\(self)------销毁了")
    }
    //MARK: 添加监听者
    private func addListener() {
        MyLog("addListener")
        wkconfiguration.userContentController.add(self, name: "print")
        wkconfiguration.userContentController.add(self, name: "pushVC")
        wkconfiguration.userContentController.add(self, name: "pushHtml")
        wkconfiguration.userContentController.add(self, name: "pop")
        wkconfiguration.userContentController.add(self, name: "httpRequest")
        wkconfiguration.userContentController.add(self, name: "makePhone")
        wkconfiguration.userContentController.add(self, name: "showMessage")
        wkconfiguration.userContentController.add(self, name: "addNavigationItem")
        wkconfiguration.userContentController.add(self, name: "custom")
        listeners.forEach { (listener) in
            if listener.isAdd == false { wkconfiguration.userContentController.add(self, name: listener.name) }
        }
    }
    //MARK: 清除监听者
    private func clearListener() {
        MyLog("clearListener")
        wkwebview.configuration.userContentController.removeAllUserScripts()
        wkconfiguration.userContentController.removeScriptMessageHandler(forName: "print")
        wkconfiguration.userContentController.removeScriptMessageHandler(forName: "pushVC")
        wkconfiguration.userContentController.removeScriptMessageHandler(forName: "pushHtml")
        wkconfiguration.userContentController.removeScriptMessageHandler(forName: "pop")
        wkconfiguration.userContentController.removeScriptMessageHandler(forName: "httpRequest")
        wkconfiguration.userContentController.removeScriptMessageHandler(forName: "makePhone")
        wkconfiguration.userContentController.removeScriptMessageHandler(forName: "showMessage")
        wkconfiguration.userContentController.removeScriptMessageHandler(forName: "addNavigationItem")
        wkconfiguration.userContentController.removeScriptMessageHandler(forName: "custom")
        listeners.forEach { (listener) in
            wkwebview.configuration.userContentController.removeScriptMessageHandler(forName: listener.name)
        }
        for i in 0..<listeners.count { listeners[i].isAdd = false }
    }
    
    func initUI() {
        let configuration = WKWebViewConfiguration()
        configuration.preferences = WKPreferences()
        configuration.preferences.javaScriptEnabled = true
        configuration.userContentController = WKUserContentController()
        wkconfiguration = configuration
        
        let webview = WKWebView.init(frame: view.bounds, configuration: configuration)
        view.addSubview(webview)
        webview.navigationDelegate = self
        wkwebview = webview
    }
    
    func initData() {
        if let _url = url { loadPage(_url) }
    }
    
    //MARK: - 加载页面
    func loadPage(_ pagePath: String) {
        if pagePath.contains("http") {//加载网络页面
            let path = URL(string: pagePath)
            if let url = path {
                wkwebview.load(URLRequest(url: url))
            }else {
                //showMessage("没有加载到页面")
                //pop()
            }
        }else {//加载本地页面
            let path = Bundle.main.path(forResource: pagePath, ofType: "html", inDirectory: "h5/html")
            MyLog(path)
            if let url = path {
                wkwebview.load(URLRequest(url: URL(fileURLWithPath: url)))
            }else {
                //showMessage("没有加载到页面")
                //pop()
            }
        }
    }
    
    //MARK: - 接收js传递的信息
    func addListener(_ name: String, _ callback:@escaping ((Any)->Void)) {
        var isNameExist = false
        for listener in listeners {
            if listener.name == name {
                isNameExist = true
                break
            }
        }
        if isNameExist == false {//没有才加
            wkconfiguration.userContentController.add(self, name: name)
            listeners.append(Listener(isAdd: true, name: name, callback: callback))
        }
    }
    //MARK: 向js传值
    func setJSObject(_ object: String, _ value: String) {
        wkwebview.evaluateJavaScript("vm.\(object) = \(value)", completionHandler: nil)
    }
    //MARK: 调用js方法
    func callJSFunctoin(_ functionName: String, _ param: String) {
        self.wkwebview.evaluateJavaScript("vm.\(functionName)(\(param))", completionHandler: nil)
    }
    
    //MARK: - 固定方法
    private func addNavigationItem(_ title: String, _ image: String, _ tag: Int, _ position: String) {
        if title == "" {//图片按钮
            if position == "right" {
                let item = UIBarButtonItem(image: UIImage(named: image), style: .plain, target: self, action: #selector(clickNavigationItem(sender:)))
                item.tag = tag
                navigationItem.rightBarButtonItem = item
            }else {
                let item = UIBarButtonItem(image: UIImage(named: image), style: .plain, target: self, action: #selector(clickNavigationItem(sender:)))
                item.tag = tag
                navigationItem.leftBarButtonItem = item
            }
        }else {
            if position == "right" {
                let item = UIBarButtonItem(title: title, style: .plain, target: self, action: #selector(clickNavigationItem(sender:)))
                item.tag = tag
                navigationItem.rightBarButtonItem = item
            }else {
                let item = UIBarButtonItem(title: title, style: .plain, target: self, action: #selector(clickNavigationItem(sender:)))
                item.tag = tag
                navigationItem.leftBarButtonItem = item
            }
        }
    }
    //MARK: 点击导航栏按钮
    @objc private func clickNavigationItem(sender: UIBarButtonItem) {
        let res = ["type": "navigationItem", "tag": "\(sender.tag)"]
        callJSFunctoin("handleClick", res.json())
    }
    
    private func pushHtml(_ url: String) {
        let vc = YLWebVC()
        vc.url = url
        navigationController?.pushViewController(vc, animated: true)
    }
    
    private func pushVC(_ vc: String) {
        let cls = NSClassFromString(nameSpace + "." + vc) as? UIViewController.Type
        if let c = cls {
            let vc = c.init()
            navigationController?.pushViewController(vc, animated: true)
        }
    }
    
    private func httpRequest(url: String, param: [String : Any]?, jsFunction: String) {
        let urlString = kUrl+url
        YLHttpManager.post(urlString: urlString, parameters: param, success: { (result) in
            MyLog(result)
            let code = result.string("code")
            if code == "1" {
                var res = result
                res["url"] = url
                DispatchQueue.main.async { self.callJSFunctoin(jsFunction, res.json()) }
            }else {
                MyLog(result.string("msg"))
            }
        }) { (error) in
            MyLog("fail")
        }
    }
    //MARK: webview代理
    func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
        
    }
    
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        navigationItem.title = webView.title
    }
    
    //处理JS交互
    public func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        MyLog(message.name)
        if message.name == "print" {
            MyLog(message.body)
        }else if message.name == "pushVC" {
            if let body = (message.body as? String) {
                pushVC(body)
            }
        }else if message.name == "pushHtml" {
            if let body = (message.body as? String) {
                pushHtml(body)
            }
        }else if message.name == "httpRequest" {
            if let body = (message.body as? [String : Any]) {
                let url = (body["url"] as? String) ?? ""
                let param = body["param"] as? [String : Any]
                let callback = (body["callback"] as? String) ?? ""
                guard url != "" else { return }
                httpRequest(url: url, param: param, jsFunction: callback)
            }
        }else if message.name == "addNavigationItem" {
            if let body = (message.body as? [String : Any]) {
                let title = body.string("title")
                let image = body.string("image")
                let position = body.string("position")
                let tag = body.int("tag")
                addNavigationItem(title, image, tag, position)
            }
        }else {
            print(listeners)
            for listener in listeners {
                print(listener)
                if listener.name == message.name {
                    listener.callback(message.body)
                    break
                }
            }
        }
    }
}
